home *** CD-ROM | disk | FTP | other *** search
/ Just Call Me Internet / Just Call Me Internet.iso / prog / atari / m2 / cat3src / cat / listman.i < prev    next >
Text File  |  1997-10-26  |  45KB  |  1,470 lines

  1. IMPLEMENTATION MODULE ListMan;
  2. (*$H+*)
  3.  
  4. FROM SYSTEM     IMPORT ADDRESS, ADR, LOC;
  5.  
  6. (* MM2 *)
  7. IMPORT GrafBase, BinOps;
  8. FROM Storage    IMPORT ALLOCATE, DEALLOCATE;
  9.  
  10. (* MagicLib *)
  11. FROM MagicSys   IMPORT sBITSET, sINTEGER, lINTEGER;
  12.  
  13. IMPORT MagicVDI, MagicAES, mtUtils, mtAppl, mtDials, mtXobjects;
  14.  
  15. (* CAT *)
  16. IMPORT DialSlider, ListUtils, RectFuncs;
  17.  
  18. FROM Void       IMPORT v;
  19.  
  20. (* Handelt scrollbare Listen in Fenstern und Dialogboxen *)
  21.  
  22. TYPE    LISTINFO    = POINTER TO listInfoType;
  23.         listInfoType= RECORD
  24.                         tree        : ADDRESS;  (* Objektbaum *)
  25.                         boxindex    : sINTEGER;
  26.                         boxbgindex  : sINTEGER;
  27.                         (* Fensterhandle. Ohne Fenster muž es < 0 sein *)
  28.                         wdw         : sINTEGER;
  29.                         (* Rechteck der Box, in dem alle Eintr„ge liegen. 
  30.                          * Nur n”tig, wenn ein wdw benutzt wird, 
  31.                          * ansonsten werden die Objektrechtecke benutzt
  32.                          *)
  33.                         area        : GrafBase.Rectangle;
  34.                         
  35.                         (* Abstand der einzelnen Eintr„ge *)
  36.                         hoffset,
  37.                         voffset     : sINTEGER;
  38.                         (* Gr”že der einzelnen Eintr„ge *)
  39.                         hsize,
  40.                         vsize       : sINTEGER;
  41.                         
  42.                         (* Koordinaten und Gr”že des vertikalen Sliders *)
  43.                         vslidx,
  44.                         vslidy,
  45.                         vslidlen    : sINTEGER;
  46.                         
  47.                         (* maximale Breite eines Eintrags. Ist dieser Wert 0,
  48.                          * so wird kein horizontaler Slider benutzt
  49.                          *)
  50.                         maxWidth    : sINTEGER;
  51.                         
  52.                         (* Schrittweite beim horizontalen Scrollen *)
  53.                         hstep       : sINTEGER;
  54.                         
  55.                         (* horizontale Position, falls hor. Slider *)
  56.                         hpos        : sINTEGER;
  57.  
  58.                         (* Koordinaten und Gr”že des horizontalen Sliders *)
  59.                         hslidx,
  60.                         hslidy,
  61.                         hslidlen    : sINTEGER;
  62.                         
  63.                         (* erster anzuzeigender Eintrag *)
  64.                         startIndex  : lINTEGER;
  65.                         
  66.                         (* letzter selektierter Eintrag *)
  67.                         lastIndex   : lINTEGER; 
  68.                         
  69.                         (* Die Liste ... *)
  70.                         list        : ADDRESS;
  71.                         
  72.                         (* ... und die Verwaltungsprozeduren dafr *)
  73.                         resetList   : ResetProc;
  74.                         nextEntry,
  75.                         prevEntry   : MoveProc;
  76.                         listElems   : CountProc;
  77.                         
  78.                         (* weitere Funktionen *)
  79.                         isEnabled       : entryIsSelectableProc;
  80.                         selEntry        : selectEntryProc;
  81.                         isSelected      : isSelectedProc;
  82.                         draw            : drawEntryProc;
  83.                         
  84.                         (* Selektionsmodus *)
  85.                         selMode         : selectMode;
  86.                         
  87.                         (* Das freie Environment *)
  88.                         env             : ADDRESS;
  89.                         
  90.                         (* Die Sachen hier k”nnen nicht extern gesetzt werden *)
  91.                         listLength      : lINTEGER;  (* Anzahl der Eintr„ge in der Liste *)
  92.                         lines           : sINTEGER;  (* Anzahl der darstellbaren Zeilen *)
  93.                         
  94.                         (* Die Sliderspecs *)
  95.                         vSlid,
  96.                         hSlid           : DialSlider.SLIDER;
  97.                         
  98.                         (* Und Zeiger auf den n„chsten fr Liste *)
  99.                         next            : LISTINFO;
  100.                       END;
  101.  
  102. VAR 
  103.         infoList        : LISTINFO;
  104.         sourceMem,
  105.         destMem         : MagicVDI.MFDB; (* Fr Rastercopy *)
  106.         deskSize        : GrafBase.Rectangle;
  107.  
  108. (* Interne Prozeduren *)
  109.  
  110.   PROCEDURE findListEntry (d : LISTINFO; index : lINTEGER) : ADDRESS;
  111.     VAR (*$Reg *)i : lINTEGER;
  112.         ptx: ADDRESS;
  113.         count : lINTEGER;
  114.         w     : sINTEGER;
  115.   BEGIN
  116.     ptx := NIL;
  117.     i := 0;
  118.     IF index < 1 THEN RETURN NIL END;
  119.     WITH d^ DO
  120.       listElems (list, count, w);
  121.       IF count > 0
  122.       THEN
  123.         d^.resetList (list);
  124.         REPEAT
  125.          ptx := nextEntry (list);
  126.          INC (i);
  127.         UNTIL (i>=index) OR (ptx = NIL);
  128.       END;
  129.     END;
  130.     RETURN ptx
  131.   END findListEntry;
  132.  
  133.   PROCEDURE findUp (VAR d : LISTINFO; index: lINTEGER): lINTEGER;
  134.     VAR pt : ADDRESS;
  135.         idx: lINTEGER;
  136.         useLI: BOOLEAN;
  137.   BEGIN
  138.     WITH d^ DO 
  139.       idx := index;
  140.       IF (index < 1) OR (index > listLength) 
  141.       THEN 
  142.         index := BinOps.LowerLInt (startIndex + LONG(lines) - 1, listLength);
  143.       END;
  144.       useLI := (lastIndex >= startIndex) & (lastIndex < startIndex + LONG(lines));
  145.       (* Hier noch Eintrag suchen, der auch angew„hlt werden kann! *)
  146.       LOOP
  147.         pt := findListEntry (d, index);
  148.         IF (pt # NIL) & isEnabled (pt, env) THEN EXIT END;
  149.         DEC (index);
  150.         IF (pt = NIL) (* OR (index < 1) *)
  151.         THEN
  152.           index := idx;
  153.           LOOP
  154.             pt := findListEntry (d, index);
  155.             IF (pt # NIL) & isEnabled (pt, env) THEN EXIT END;
  156.             INC (index);
  157.             IF (pt = NIL) (* OR ((lastIndex > 0) & (index > lastIndex)) *)
  158.             THEN
  159.               index := -1;
  160.               EXIT
  161.             END;
  162.           END; (* Loop *)
  163.           EXIT
  164.         END;
  165.       END; (* Loop *)
  166.       IF useLI & (lastIndex > 0) & (index > lastIndex) THEN 
  167.         RETURN lastIndex 
  168.       ELSE 
  169.         RETURN index 
  170.       END;
  171.     END (* WITH *)
  172.   END findUp;
  173.  
  174.   PROCEDURE findDown (VAR d : LISTINFO; index : lINTEGER): lINTEGER;
  175.     VAR pt : ADDRESS;
  176.         idx: lINTEGER;
  177.         useLI : BOOLEAN;
  178.   BEGIN
  179.     WITH d^ DO 
  180.       idx := index;
  181.       IF (index < 1) OR
  182.          (index > listLength) 
  183.       THEN 
  184.         index := startIndex
  185.       END;
  186.       useLI := (lastIndex >= startIndex) & (lastIndex < startIndex + LONG(lines));
  187.       (* Hier noch Eintrag suchen, der auch angew„hlt werden kann! *)
  188.       LOOP
  189.         pt := findListEntry (d, index);
  190.         IF (pt # NIL) & isEnabled (pt, env) THEN EXIT END;
  191.         INC (index);
  192.         IF (pt = NIL) (* OR (index > listLength) *)
  193.         THEN 
  194.           index := idx;
  195.           LOOP
  196.             pt := findListEntry (d, index);
  197.             IF (pt # NIL) & isEnabled (pt, env) THEN EXIT END;
  198.             DEC (index);
  199.             IF (pt = NIL) (* OR (index < lastIndex) *)
  200.             THEN
  201.               index := -1;
  202.               EXIT
  203.             END;
  204.           END; (* Loop *)
  205.           EXIT
  206.         END;
  207.       END; (* Loop *)
  208.       IF useLI & (index < lastIndex) THEN
  209.         RETURN lastIndex
  210.       ELSE
  211.         RETURN index
  212.       END;
  213.     END (* WITH *)
  214.   END findDown;
  215.   
  216.   PROCEDURE positionList (listInfo: LISTINFO);
  217.   BEGIN
  218.     WITH listInfo^ DO
  219.       IF (wdw < 0) & (tree # NIL)
  220.       THEN
  221.         mtUtils.CalcArea (tree, boxindex, area);
  222.       END;
  223.       (* Position berechnen *)
  224.       vslidx := area.x + area.w-1;
  225.       vslidy := area.y;
  226.       vslidlen := area.h;
  227.       DialSlider.SliderExtents (vSlid, vslidx, vslidy, vslidlen, FALSE);
  228.       hslidx := area.x;
  229.       hslidy := area.y+area.h-1;
  230.       hslidlen := area.w;
  231.       DialSlider.SliderExtents (hSlid, hslidx, hslidy, hslidlen, FALSE);
  232.     END;
  233.   END positionList;
  234.   
  235.   PROCEDURE calcEntryPos (d: LISTINFO; pos : sINTEGER; 
  236.                           VAR r : ARRAY OF LOC);
  237.   (* Berechnet den Platz eines Eintrages 
  238.    *)
  239.     VAR rect : GrafBase.Rectangle;
  240.         r2   : POINTER TO GrafBase.Rectangle;
  241.   BEGIN
  242.     WITH d^ DO
  243.       r2 := ADR (r);
  244.       (* Basisrechteck berechnen *)
  245.       IF tree # NIL
  246.       THEN
  247.         mtUtils.ObjcArea (tree, boxindex, rect);
  248.       ELSE
  249.         rect := area
  250.       END;
  251.       r2^ := rect;
  252.       (* Jetzt die Position berechnen *)
  253.       r2^.x := r2^.x - hpos;
  254.       r2^.y := r2^.y + pos * (vsize+voffset);
  255.       r2^.h := vsize + voffset;
  256.       (*
  257.       (* Und jetzt noch clippen *)
  258.       r2^ := RectFuncs.ClipRect (r2^, rect);
  259.       *)
  260.     END;
  261.   END calcEntryPos;
  262.  
  263.   PROCEDURE showEntry (d : LISTINFO; index : lINTEGER; pos : sINTEGER; 
  264.                        clip: GrafBase.Rectangle);
  265.     VAR (*$Reg*) ptx     : ADDRESS;
  266.         r, r2            : GrafBase.Rectangle;
  267.         cr               : GrafBase.Rectangle;
  268.   BEGIN
  269.    WITH d^ DO
  270.     mtUtils.ObjcArea (tree, boxindex, r2);
  271.     cr := RectFuncs.ClipRect (r2, clip);
  272.     ptx := findListEntry (d, index);
  273.     calcEntryPos (d, pos, r);
  274.     IF tree # NIL
  275.     THEN
  276.       draw (ptx, env, r.x, r.y, hpos, cr)
  277.     ELSE
  278.       (* Vorerst nichts *)
  279.     END;
  280.    END;
  281.   END showEntry;
  282.  
  283.   PROCEDURE showAll (VAR d : LISTINFO; clip : GrafBase.Rectangle);
  284.     VAR j    : sINTEGER;
  285.         ptx  : ADDRESS;
  286.         r, r2: GrafBase.Rectangle;
  287.         cr   : GrafBase.Rectangle;
  288.   BEGIN
  289.    IF (clip.w = 0) OR (clip.h = 0) THEN RETURN END;
  290.    WITH d^ DO
  291.     mtUtils.ObjcArea (tree, boxindex, r2);
  292.     cr := RectFuncs.ClipRect (r2, clip);
  293.     j := 0;
  294.     IF startIndex < 1 THEN startIndex := 1 END;
  295.     ptx := findListEntry (d, startIndex);
  296.     REPEAT
  297.       calcEntryPos (d, j, r);
  298.       IF ptx # NIL
  299.       THEN
  300.         draw (ptx, env, r.x, r.y, hpos, cr);
  301.         ptx := nextEntry (list);
  302.       ELSE
  303.         draw (NIL, env, r.x, r.y, hpos, cr);
  304.       END;
  305.       INC(j);
  306.     UNTIL (j>=lines);
  307.    END;
  308.   END showAll;
  309.  
  310.   PROCEDURE scrollV (VAR d : LISTINFO; newStart : lINTEGER);
  311.     VAR j    : lINTEGER;
  312.         redraw  : GrafBase.Rectangle;
  313.         diff    : lINTEGER;
  314.         oldStart : lINTEGER;
  315.         rect,
  316.         r1, r2 : mtUtils.tRect;
  317.         upperFrame, 
  318.         lowerFrame : mtUtils.tRect;
  319.         two     : ListUtils.TwoRects;
  320.   BEGIN
  321.    WITH d^ DO
  322.     IF newStart < 1 THEN newStart := 1 END;
  323.     oldStart := startIndex;
  324.     IF newStart = startIndex THEN RETURN END;
  325.     startIndex := newStart;
  326.     
  327.     mtUtils.ObjcArea (tree, boxindex, redraw);
  328.     diff := ABS (oldStart - newStart);
  329.     IF (diff < LONG(lines))
  330.     THEN
  331.       
  332.       (* calculate upper & lower frame for BitBlk *)
  333.       mtUtils.ObjcArea (tree, boxindex, rect);
  334.       r1 := rect; 
  335.       r1.h := vsize + voffset;
  336.       r2 := r1;
  337.       r2.y := r2.y + (lines-1-SHORT(diff))*(vsize+voffset);
  338.       upperFrame := ListUtils.FrameRects (r1, r2);
  339.  
  340.       r1 := rect; 
  341.       r1.y := r1.y + SHORT(diff)*(vsize+voffset);
  342.       r1.h := vsize + voffset;
  343.       r2 := rect;
  344.       r2.h := vsize + voffset;
  345.       r2.y := r2.y + (lines-1)*(vsize+voffset);
  346.  
  347.       lowerFrame := ListUtils.FrameRects (r1, r2);
  348.       lowerFrame := mtUtils.tRect(RectFuncs.ClipRect (GrafBase.Rectangle(lowerFrame), deskSize));
  349.       upperFrame := mtUtils.tRect(RectFuncs.ClipRect (GrafBase.Rectangle(upperFrame), deskSize));
  350.     
  351.       IF newStart < oldStart THEN
  352.         two := ListUtils.WordArray (upperFrame, lowerFrame)
  353.       ELSE
  354.         two := ListUtils.WordArray (lowerFrame, upperFrame)
  355.       END;
  356.       mtAppl.MouseOff;
  357.  
  358.       MagicVDI.CopyRasterOpaque (mtAppl.PrivateWS, 3, two,
  359.                                  sourceMem, destMem);
  360.  
  361.       IF newStart < oldStart 
  362.       THEN
  363.         (* von oben neu Zeichnen *)
  364.         FOR j := 0 TO diff-1 DO
  365.           showEntry (d, startIndex+j, SHORT (j), redraw);
  366.         END;
  367.       ELSE
  368.         (* von unten neu zeichen *)
  369.         FOR j := diff TO 1 BY -1 DO
  370.           showEntry (d, startIndex+LONG(lines)-j, lines - SHORT (j), redraw);
  371.         END
  372.       END;
  373.       mtAppl.MouseOn;
  374.     ELSE
  375.       showAll (d, redraw);
  376.     END;
  377.    END;
  378.   END scrollV;
  379.   
  380.   PROCEDURE scrollH (VAR d : LISTINFO; newPos : sINTEGER);
  381.     VAR j    : sINTEGER;
  382.         redraw  : GrafBase.Rectangle;
  383.         diff    : sINTEGER;
  384.         oldStart : sINTEGER;
  385.         r1, r2 : mtUtils.tRect;
  386.         leftFrame, 
  387.         rightFrame : mtUtils.tRect;
  388.         two     : ListUtils.TwoRects;
  389.   BEGIN
  390.    WITH d^ DO
  391.     IF newPos < 0 THEN newPos := 0 END;
  392.     oldStart := hpos;
  393.     IF newPos = hpos THEN RETURN END;
  394.     hpos := newPos;
  395.     
  396.     mtUtils.ObjcArea (tree, boxindex, redraw);
  397.     redraw :=  RectFuncs.ClipRect (redraw, deskSize);
  398.     diff := ABS (oldStart - hpos);
  399.     IF (diff < redraw.w)
  400.     THEN
  401.       
  402.       (* calculate left & right frame for BitBlk *)
  403.       leftFrame := mtUtils.tRect (redraw);
  404.       DEC (leftFrame.w, diff);
  405.       rightFrame := leftFrame;
  406.       INC(rightFrame.x, diff);
  407.  
  408.       mtUtils.CalcArea (tree, boxindex, r1);
  409.       r1 :=  mtUtils.tRect(RectFuncs.ClipRect (GrafBase.Rectangle(r1), deskSize));
  410.       IF newPos < oldStart THEN
  411.         two := ListUtils.WordArray (leftFrame, rightFrame);
  412.       ELSE
  413.         two := ListUtils.WordArray (rightFrame, leftFrame);
  414.         r1.x := r1.x + r1.w - 1 - diff;
  415.       END;
  416.       r1.w := diff+1;
  417.       mtAppl.MouseOff;
  418.  
  419.       MagicVDI.CopyRasterOpaque (mtAppl.PrivateWS, 3, two,
  420.                                  sourceMem, destMem);
  421.       
  422.       (* Jetzt Teilbereich neu zeichnen *)
  423.       showAll (d, GrafBase.Rectangle (r1));
  424.       (*
  425.       FOR j := 0 TO lines - 1 DO
  426.         showEntry (d, startIndex+LONG(j), j, GrafBase.Rectangle(r1));
  427.       END;
  428.       *)
  429.       mtAppl.MouseOn;
  430.     ELSE
  431.       showAll (d, redraw);
  432.     END;
  433.    END;
  434.   END scrollH;
  435.  
  436.   PROCEDURE CenterEntry (VAR d : LISTINFO; entry : lINTEGER; drawIt: BOOLEAN);
  437.     VAR newStart : lINTEGER;
  438.         halfSize : lINTEGER;
  439.   BEGIN
  440.     WITH d^ DO
  441.       positionList (d);
  442.       IF entry < 1 THEN RETURN END;
  443.       IF (entry < startIndex) OR (entry >= startIndex + LONG(lines))
  444.       THEN
  445.         halfSize := lines DIV 2;
  446.         IF entry > halfSize THEN
  447.           newStart := entry - halfSize;
  448.         ELSE 
  449.           newStart := entry;
  450.         END;
  451.         IF newStart > listLength - LONG(lines)
  452.         THEN
  453.           newStart := listLength - LONG(lines)+1
  454.         END;
  455.         IF drawIt THEN scrollV (d, newStart); END;
  456.         startIndex := newStart;
  457.         IF drawIt THEN DialSlider.SetSliderPos (vSlid, startIndex-1, TRUE) END;
  458.       END;
  459.     END;
  460.   END CenterEntry;
  461.   
  462. PROCEDURE InitList (list : ADDRESS; 
  463.                     env  : ADDRESS;
  464.                     selectEntry       : selectEntryProc;
  465.                     isSelectedEntry   : isSelectedProc;
  466.                     isSelectableEntry : entryIsSelectableProc;
  467.                     drawEntry         : drawEntryProc;
  468.                     resetList         : ResetProc;
  469.                     nextList,
  470.                     prevList          : MoveProc;
  471.                     countList         : CountProc;
  472.                     select            : selectMode;
  473.                     VAR listInfo      : LISTINFO): BOOLEAN;
  474.   VAR   i : sINTEGER;
  475.         halfSize : sINTEGER;
  476.         bFrame,
  477.         pFrame, 
  478.         sFrame  : GrafBase.Rectangle;
  479.         d2      : LISTINFO;
  480. BEGIN
  481.   NEW (listInfo);
  482.   IF listInfo = NIL THEN RETURN FALSE END;
  483.   (* Jetzt in Liste h„ngen *)
  484.   IF infoList = NIL 
  485.   THEN 
  486.     infoList := listInfo
  487.   ELSE
  488.     d2 := infoList;
  489.     WHILE d2^.next # NIL DO
  490.       d2 := d2^.next;
  491.     END;
  492.     d2^.next := listInfo;
  493.   END;
  494.   listInfo^.next := NIL;
  495.   listInfo^.list       := list;
  496.   listInfo^.env        := env       ;
  497.   listInfo^.selEntry   := selectEntry  ;
  498.   listInfo^.isEnabled  := isSelectableEntry ;
  499.   listInfo^.isSelected := isSelectedEntry;
  500.   listInfo^.draw       := drawEntry ;
  501.   
  502.   listInfo^.resetList  := resetList;
  503.   listInfo^.nextEntry  := nextList ;
  504.   listInfo^.prevEntry  := prevList ;
  505.   listInfo^.listElems  := countList;
  506.   listInfo^.selMode    := select;
  507.  
  508.   listInfo^.tree       := NIL;
  509.   listInfo^.wdw        := -1;
  510.   
  511.   (* Jetzt noch ein paar Sachen initialisieren *)
  512.   listInfo^.vSlid      := DialSlider.SLIDER (NIL);
  513.   listInfo^.hSlid      := DialSlider.SLIDER (NIL);
  514.   
  515.   listInfo^.lastIndex := -1;
  516.   listInfo^.startIndex := 1;
  517.   listInfo^.hoffset    := 0;
  518.   listInfo^.hpos       := 0;
  519.   
  520.   RETURN TRUE
  521. END InitList;
  522.  
  523. (* Von den beiden folgenden Prozeduren muž mindestens eine nach 
  524.  * der Initialisierung der Liste aufgerufen werden
  525.  *)
  526.  
  527. PROCEDURE SetListWdwSpecs (listInfo: LISTINFO; 
  528.                            wdwHandle  : sINTEGER;
  529.                            rect       : GrafBase.Rectangle;
  530.                            voffset    : sINTEGER;
  531.                            vsize      : sINTEGER;
  532.                            hstep      : sINTEGER;
  533.                            maxwidth   : sINTEGER): BOOLEAN;
  534. (* Setzt weitere Informationen fr die Liste. 
  535.  * wdwHandle: Das Fenster, in dem die Liste dargestellt wird
  536.  * area: Arbeitsbereich, in dem die Liste dargestellt wird
  537.  * voffset: Abstand zwischen zwei Eintr„gen
  538.  * vsize  : H”he eines Eintrages
  539.  * maxwidth: maximale Breite eines Eintrags
  540.  *)
  541. BEGIN
  542.   RETURN FALSE
  543. END SetListWdwSpecs;
  544.  
  545. PROCEDURE listDrawForeground (p: MagicAES.PtrPARMBLK): sBITSET; FORWARD;
  546. PROCEDURE listDrawBackground (p: MagicAES.PtrPARMBLK): sBITSET; FORWARD;
  547.  
  548. PROCEDURE SetListDialSpecs(listInfo: LISTINFO; 
  549.                            tree       : ADDRESS;
  550.                            entryBox   : sINTEGER;
  551.                            boxBack    : sINTEGER;
  552.                            voffset    : sINTEGER;
  553.                            vsize      : sINTEGER;
  554.                            hstep      : sINTEGER;
  555.                            maxwidth   : sINTEGER): BOOLEAN;
  556. (* Setzt weitere Informationen fr die Liste. 
  557.  * tree: Der Baum, in dem die Liste dargestellt wird
  558.  * entryBox: Objektindex fr das Objekt, in dem alle Objekte 
  559.  *           dargestellt werden
  560.  * boxBack: Objektindex des Hintergrundes der Box (fr Slider)
  561.  * voffset: Abstand zwischen zwei Eintr„gen
  562.  * vsize  : H”he eines Eintrages
  563.  * maxwidth: maximale Breite eines Eintrags (wenn = 0, dann wird kein
  564.  * horizontaler Slider eingesetzt)
  565.  *)
  566.  VAR backrect : GrafBase.Rectangle;
  567.      cliparea : GrafBase.Rectangle;
  568. BEGIN
  569.   listInfo^.tree := tree;
  570.   listInfo^.boxindex    := entryBox;
  571.   listInfo^.boxbgindex  := boxBack;
  572.   listInfo^.voffset     := voffset;
  573.   listInfo^.vsize       := vsize;
  574.   listInfo^.hstep       := hstep;
  575.   listInfo^.maxWidth    := maxwidth;
  576.   (* Ok, und  jetzt k”nnen wir die Slider initialisieren *)
  577.   WITH listInfo^ DO
  578.     (* Das ist der Workbereich *)
  579.     mtUtils.ObjcArea (tree, boxindex, area);
  580.     (* Das brauchen wir fr die Slider *)
  581.     mtUtils.ObjcRect (tree, boxbgindex, backrect);
  582.     (* Anpassen an Rand der Slider *)
  583.     INC (backrect.w);
  584.     IF maxwidth > 0 THEN INC (backrect.h); END;
  585.     mtUtils.SetObjcRect (tree, boxbgindex, backrect);
  586.     (* Anzahl Zeilen berechnen *)
  587.     lines := area.h DIV (vsize + voffset);
  588.     (* area clippen auf Vielfaches der H”he *)
  589.     mtUtils.ObjcRect (tree, boxindex, cliparea);
  590.     cliparea.h := lines * (vsize + voffset);
  591.     mtUtils.SetObjcRect (tree, boxindex, cliparea);
  592.     (* Jetzt den vertikalen Slider plazieren *)
  593.     listElems (list, listLength, v.int);
  594.     v.bool := DialSlider.CreateSlider (vSlid, FALSE, 1, lines, listLength, startIndex - 1);
  595.     IF ~v.bool THEN RETURN FALSE END;
  596.     IF maxWidth > 0 
  597.     THEN
  598.       (* auch horizontalen Slider erzeugen *)
  599.       v.bool := DialSlider.CreateSlider (hSlid, TRUE, hstep, area.w, maxWidth, hpos);
  600.       IF ~v.bool THEN RETURN FALSE END;
  601.     END;
  602.     (*
  603.     (* Und jetzt werden die Userdefs installiert fr die Boxen *)
  604.     v.bool := mtXobjects.InstUserdef (tree, boxindex, listDrawForeground, listInfo);
  605.     v.bool := mtXobjects.InstUserdef (tree, boxbgindex, listDrawBackground, listInfo);
  606.     *)
  607.   END;
  608.   RETURN TRUE;
  609. END SetListDialSpecs;
  610.  
  611. PROCEDURE FreeList (listInfo: LISTINFO): BOOLEAN;
  612. (* gibt einen Listenhandler wieder frei. *)
  613.   VAR d2 : LISTINFO;
  614.       m  : sINTEGER;
  615.       backrect : GrafBase.Rectangle;
  616. BEGIN
  617.   IF listInfo = NIL THEN RETURN FALSE END;
  618.   d2 := infoList;
  619.   IF d2 = listInfo
  620.   THEN
  621.     infoList := listInfo^.next;
  622.   ELSE
  623.     WHILE (d2 # NIL) & (d2^.next # listInfo) DO 
  624.       d2 := d2^.next;
  625.     END;
  626.     IF d2 = NIL
  627.     THEN RETURN FALSE
  628.     END;
  629.     (* listInfo aush„ngen *)
  630.     d2^.next := listInfo^.next;
  631.   END;
  632.   WITH listInfo^ DO
  633.     (* Jetzt Slider freigeben *)
  634.     IF ADDRESS(vSlid) # NIL
  635.     THEN
  636.       DialSlider.FreeSlider (vSlid);
  637.     END;
  638.     IF ADDRESS(hSlid) # NIL
  639.     THEN
  640.       DialSlider.FreeSlider (hSlid);
  641.     END;
  642.     IF tree # NIL
  643.     THEN
  644.       (* Userdefs freigeben *)
  645.       mtXobjects.FreeUserdef (tree, boxbgindex);
  646.       mtXobjects.FreeUserdef (tree, boxindex);
  647.       mtUtils.ObjcRect (tree, boxbgindex, backrect);
  648.       (* Anpassen an Rand der Slider *)
  649.       DEC (backrect.w);
  650.       IF maxWidth > 0 THEN DEC (backrect.h); END;
  651.       mtUtils.SetObjcRect (tree, boxbgindex, backrect);
  652.     END;
  653.   END;
  654.   DISPOSE (listInfo);
  655.   RETURN TRUE
  656. END FreeList;
  657.  
  658. PROCEDURE internalDrawList (listInfo: LISTINFO; clip : GrafBase.Rectangle;
  659.                             showList: BOOLEAN; posSlider: BOOLEAN;
  660.                             showSlider: BOOLEAN);
  661.   VAR cr : GrafBase.Rectangle;
  662.       ll : lINTEGER;
  663.       ww : sINTEGER;
  664. BEGIN
  665.   (* Zeichnet die Liste neu und auch die Slider, Clipping wird
  666.    * beachtet
  667.    *)
  668.   WITH listInfo^ DO
  669.     IF tree # NIL
  670.     THEN
  671.       mtUtils.CalcArea (tree, boxindex, area);
  672.       mtUtils.ObjcArea (tree, boxindex, cr);
  673.     ELSE
  674.       cr := area;
  675.     END;
  676.     IF posSlider 
  677.     THEN
  678.       listElems (list, ll, ww);
  679.       IF listLength  # ll
  680.       THEN
  681.         listLength := ll;
  682.         DialSlider.SetSliderScale (vSlid, listLength);
  683.         (* Jetzt noch evtl. lastIndex updaten *)
  684.         IF startIndex + (LONG(lines) - 1) > listLength
  685.         THEN
  686.           startIndex := listLength - LONG (lines);
  687.         END;
  688.         lastIndex := ListFirstSelected (listInfo);
  689.         (*
  690.         IF selMode = smOne
  691.         THEN
  692.           ListScroll2Selection (listInfo, TRUE);
  693.         END;
  694.         *)
  695.       END;
  696.       IF (maxWidth > 0) & (ww > 0) & (maxWidth # ww)
  697.       THEN
  698.         maxWidth := ww;
  699.         DialSlider.SetSliderScale (hSlid, maxWidth);
  700.         hpos := 0;
  701.       END;
  702.     END;
  703.     cr := RectFuncs.ClipRect (clip, cr);
  704.     IF showList
  705.     THEN
  706.       showAll (listInfo, cr);
  707.     END;
  708.     positionList (listInfo);
  709.     IF showSlider
  710.     THEN
  711.       DialSlider.SetSliderPos (vSlid, startIndex-1, FALSE);
  712.       DialSlider.DrawSlider (vSlid, mtUtils.tRect(clip), TRUE);
  713.       DialSlider.DrawSlider (hSlid, mtUtils.tRect(clip), TRUE);
  714.     END;
  715.   END;
  716. END internalDrawList;
  717.  
  718. PROCEDURE DrawList (listInfo: LISTINFO; clip : GrafBase.Rectangle);
  719.   VAR cr : GrafBase.Rectangle;
  720.       ll : lINTEGER;
  721.       ww : sINTEGER;
  722. BEGIN
  723.   (* Zeichnet die Liste neu und auch die Slider, Clipping wird
  724.    * beachtet
  725.    *)
  726.   WITH listInfo^ DO
  727.     (*
  728.     IF tree # NIL
  729.     THEN
  730.       mtDials.DialDraw (listInfo^.tree, boxbgindex, 2, clip, TRUE);
  731.     ELSE
  732.       internalDrawList (listInfo, clip, TRUE, TRUE, TRUE);
  733.     END;
  734.     *)
  735.     internalDrawList (listInfo, clip, TRUE, TRUE, TRUE);
  736.   END;
  737.   (*
  738.   WITH listInfo^ DO
  739.     IF tree # NIL
  740.     THEN
  741.       mtUtils.CalcArea (tree, boxindex, area);
  742.       mtUtils.ObjcArea (tree, boxindex, cr);
  743.     ELSE
  744.       cr := area;
  745.     END;
  746.     listElems (list, ll, ww);
  747.     IF listLength  # ll
  748.     THEN
  749.       listLength := ll;
  750.       DialSlider.SetSliderScale (vSlid, listLength);
  751.       (* Jetzt noch evtl. lastIndex updaten *)
  752.       IF startIndex + (LONG(lines) - 1) > listLength
  753.       THEN
  754.         startIndex := listLength - LONG (lines);
  755.       END;
  756.       lastIndex := ListFirstSelected (listInfo);
  757.       (*
  758.       IF selMode = smOne
  759.       THEN
  760.         ListScroll2Selection (listInfo, TRUE);
  761.       END;
  762.       *)
  763.     END;
  764.     IF (maxWidth > 0) & (ww > 0) & (maxWidth # ww)
  765.     THEN
  766.       maxWidth := ww;
  767.       DialSlider.SetSliderScale (hSlid, maxWidth);
  768.     END;
  769.     cr := RectFuncs.ClipRect (clip, cr);
  770.     showAll (listInfo, cr);
  771.     positionList (listInfo);
  772.     DialSlider.SetSliderPos (vSlid, startIndex-1, FALSE);
  773.     DialSlider.DrawSlider (vSlid, mtUtils.tRect(clip), FALSE);
  774.     DialSlider.DrawSlider (hSlid, mtUtils.tRect(clip), FALSE);
  775.   END;
  776.   *)
  777. END DrawList;
  778.  
  779. PROCEDURE listDrawBackground (p: MagicAES.PtrPARMBLK): sBITSET;
  780.   VAR d: LISTINFO;
  781.       found: BOOLEAN;
  782.       r    : GrafBase.Rectangle;
  783. BEGIN
  784.   (* Listinfo suchen auf Grund von tree und obIndex *)
  785.   d := infoList;
  786.   found := FALSE;
  787.   REPEAT
  788.     IF d # NIL 
  789.     THEN
  790.       IF (d^.tree = p^.pbTree) & (d^.boxbgindex = p^.pbObj)
  791.       THEN
  792.         (* gefunden! *)
  793.         found := TRUE
  794.       ELSE
  795.         d := d^.next;
  796.       END;
  797.     END;
  798.   UNTIL (d = NIL) OR found;
  799.   IF d # NIL
  800.   THEN
  801.     WITH p^ DO
  802.       (* Rahmen zeichnen *)
  803.       mtDials.Frame (pbX, pbY, pbW, pbH, 1);
  804.       r.x := pbXc;
  805.       r.y := pbYc;
  806.       r.w := pbWc;
  807.       r.h := pbHc;
  808.     END;
  809.     internalDrawList (d, r, FALSE, TRUE, TRUE);
  810.   END;
  811.   RETURN {};
  812. END listDrawBackground;
  813.  
  814. PROCEDURE listDrawForeground (p: MagicAES.PtrPARMBLK): sBITSET;
  815.   VAR d: LISTINFO;
  816.       found: BOOLEAN;
  817.       r    : GrafBase.Rectangle;
  818. BEGIN
  819.   (* Listinfo suchen auf Grund von tree und obIndex *)
  820.   d := infoList;
  821.   found := FALSE;
  822.   REPEAT
  823.     IF d # NIL 
  824.     THEN
  825.       IF (d^.tree = p^.pbTree) & (d^.boxindex = p^.pbObj)
  826.       THEN
  827.         (* gefunden! *)
  828.         found := TRUE
  829.       ELSE
  830.         d := d^.next;
  831.       END;
  832.     END;
  833.   UNTIL (d = NIL) OR found;
  834.   IF d # NIL
  835.   THEN
  836.     WITH p^ DO
  837.       (* Rahmen zeichnen *)
  838.       mtDials.Frame (pbX, pbY, pbW, pbH, 1);
  839.       r.x := pbXc;
  840.       r.y := pbYc;
  841.       r.w := pbWc;
  842.       r.h := pbHc;
  843.     END;
  844.     internalDrawList (d, r, TRUE, TRUE, FALSE);
  845.   END;
  846.   RETURN {};
  847. END listDrawForeground;
  848.  
  849. PROCEDURE deselectEntry (listInfo: LISTINFO; index: lINTEGER; show: BOOLEAN);
  850.   VAR entry, lastEntry : ADDRESS;
  851.       line             : INTEGER;
  852. BEGIN
  853.   WITH listInfo^ DO
  854.     IF selMode = smOne
  855.     THEN
  856.       (* einfach nur deselektieren *)
  857.       entry := findListEntry (listInfo, index);
  858.       (* Eintrag ist selektierbar *)
  859.       IF (entry # NIL) & isEnabled (entry, env) & isSelected (entry, env)
  860.       THEN
  861.         (* Jetzt Eintrag (de-)selektieren *)
  862.         IF (index >= startIndex) & (index < startIndex + LONG(lines)) & show
  863.         THEN
  864.           line := SHORT(index - startIndex);
  865.         ELSE
  866.           line := -1
  867.         END;
  868.         v.bool := selEntry (entry, env, line);
  869.         IF (index >= startIndex) & (index < startIndex + LONG(lines))
  870.         THEN
  871.           showEntry (listInfo, index, SHORT(index - startIndex), area);
  872.         END;
  873.         lastIndex := -1;
  874.       END;
  875.     END;
  876.   END;
  877. END deselectEntry;
  878.  
  879. PROCEDURE selectEntry (listInfo: LISTINFO; index: lINTEGER; 
  880.                        VAR isSel: BOOLEAN; show: BOOLEAN; byClick: BOOLEAN; 
  881.                        clicks: INTEGER);
  882.   VAR entry, lastEntry : ADDRESS;
  883.       line             : INTEGER;
  884. BEGIN
  885.   WITH listInfo^ DO
  886.     IF selMode = smNone
  887.     THEN
  888.       RETURN 
  889.     ELSIF selMode = smOne
  890.     THEN
  891.       IF (index # lastIndex) OR byClick
  892.       THEN
  893.         (* Ok, wirklich neuer Eintrag *)
  894.         entry := findListEntry (listInfo, index);
  895.         (* Eintrag ist selektierbar *)
  896.         isSel := (entry # NIL) & isEnabled (entry, env);
  897.         IF (entry # NIL) & isSel 
  898.         THEN
  899.           (* eventuell selektierten Eintrag deselektieren *)
  900.           IF index # lastIndex
  901.           THEN
  902.             lastEntry := findListEntry (listInfo, lastIndex);
  903.             IF (lastEntry # NIL) & isSelected (lastEntry, env)
  904.             THEN
  905.               v.bool := selEntry (lastEntry, env, -1);
  906.               (* Jetzt eventuell neu zeichnen *)
  907.               IF (lastIndex >= startIndex) & (lastIndex < startIndex + LONG(lines))
  908.               THEN
  909.                 showEntry (listInfo, lastIndex, SHORT(lastIndex - startIndex), area);
  910.               END;
  911.             END;
  912.           END;
  913.           (* Jetzt neuen Eintrag selektieren *)
  914.           IF (index >= startIndex) & (index < startIndex + LONG(lines)) & show
  915.           THEN
  916.             line := SHORT(index - startIndex);
  917.           ELSE
  918.             line := -1
  919.           END;
  920.           IF (entry # NIL) & isSelected (entry, env) & byClick & (clicks > 1)
  921.           THEN
  922.           ELSE
  923.             v.bool := selEntry (entry, env, line);
  924.           END;
  925.           IF (index >= startIndex) & (index < startIndex + LONG(lines))
  926.           THEN
  927.             showEntry (listInfo, index, SHORT(index - startIndex), area);
  928.           END;
  929.           lastIndex := index;
  930.         END;
  931.       END;
  932.     ELSIF selMode = smMulti
  933.     THEN
  934.       entry := findListEntry (listInfo, index);
  935.       isSel := isEnabled (entry, env);
  936.       IF (entry # NIL) & isEnabled (entry, env)
  937.       THEN
  938.         (* Neuen Eintrag selektieren *)
  939.         IF (index >= startIndex) & (index < startIndex + LONG(lines)) & show
  940.         THEN
  941.           line := SHORT(index - startIndex);
  942.         ELSE
  943.           line := -1
  944.         END;
  945.         v.bool := selEntry (entry, env, line);
  946.         IF (index >= startIndex) & (index < startIndex + LONG(lines))
  947.         THEN
  948.           showEntry (listInfo, index, SHORT(index - startIndex), area);
  949.         END;
  950.       END;
  951.     END;
  952.   END;
  953. END selectEntry;
  954.  
  955. VAR slidInfo : LISTINFO;
  956.  
  957. PROCEDURE slidVertical (slid: DialSlider.SLIDER; newPos : LONGINT);
  958. BEGIN
  959.   scrollV (slidInfo, newPos+1);
  960. END slidVertical;
  961.  
  962. PROCEDURE slidHorizontal (slid: DialSlider.SLIDER; newPos : LONGINT);
  963. BEGIN
  964.   scrollH (slidInfo, SHORT(newPos));
  965. END slidHorizontal;
  966.  
  967. PROCEDURE ListClick (listInfo: LISTINFO; mx, my: INTEGER; kstate: BITSET; 
  968.                      clicks: sINTEGER): lINTEGER;
  969. (* Wird aufgerufen, wenn ein Mausklick stattfand. Gibt zurck,
  970.  * ob ein Eintrag angeklickt wurde (>= 0) oder ob 
  971.  * der Click aužerhalb des Bereiches war (-1)
  972.  * oder ob der Click behandelt wurde (-2)
  973.  * Wenn ein Eintrag angeklickt wurde, dann wird dieser auch selektiert,
  974.  * falls notwendig.
  975.  *)
  976.   VAR saveIndex,
  977.       oldIndex  : lINTEGER;
  978.       i         : lINTEGER;
  979.       button    : sBITSET;
  980.       elem      : lINTEGER;
  981.       selIndex, 
  982.       index     : lINTEGER;
  983.       isSel     : BOOLEAN;
  984.       br        : GrafBase.Rectangle;
  985. BEGIN
  986.   WITH listInfo^ DO
  987.     positionList (listInfo);
  988.     (* Erstmal nachsehen, ob auf einen Slider geclickt wurde *)
  989.     slidInfo := listInfo;
  990.     elem := DialSlider.SliderClick (vSlid, mx, my, clicks, slidVertical);
  991.     IF elem >= 0
  992.     THEN 
  993.       RETURN -2
  994.     END;
  995.     elem := DialSlider.SliderClick (hSlid, mx, my, clicks, slidHorizontal);
  996.     IF elem >= 0
  997.     THEN 
  998.       RETURN -2
  999.     END;
  1000.     (* Nicht auf einen der Slider, nachsehen, ob es im Workbereich ist *)
  1001.     IF RectFuncs.IsInRect (mx, my, area)
  1002.     THEN
  1003.       (* Ist im Workbereich, behandeln *)
  1004.       index := startIndex + LONG((my - area.y) DIV (vsize + voffset));
  1005.       IF (clicks >0) & (index <= listLength)
  1006.       THEN
  1007.         (* Element getroffen, selektieren. Falls Maustaste gedrckt bleibt, 
  1008.          * dann Bereich selektieren (je nach SelectMode)
  1009.          *)
  1010.         selectEntry (listInfo, index, isSel, TRUE, TRUE, clicks);
  1011.         IF ~isSel THEN index := -1 END;
  1012.         
  1013.         saveIndex := index;
  1014.         (* Jetzt feststellen, ob Maustaste noch gedrckt ist und
  1015.          * dann in ScrollModus bergehen, aber nur wenn multiple erlaubt 
  1016.          * ist.
  1017.          *)
  1018.         MagicAES.GrafMkstate (mx, my, button, kstate);
  1019.         (* Jetzt Baserechteck berechnen und Object unter Mauskoordinaten
  1020.          * suchen 
  1021.          *)
  1022.         oldIndex := index;
  1023.         WHILE (0 IN button) DO 
  1024.           index := startIndex + LONG((my - area.y) DIV (vsize + voffset));
  1025.           IF (index < startIndex) OR (my < area.y)
  1026.           THEN
  1027.             (* scrollen *)
  1028.             ListLnUp (listInfo);
  1029.           ELSIF index >= startIndex + LONG(lines)
  1030.           THEN
  1031.             ListLnDown (listInfo);
  1032.           END;
  1033.           IF selMode = smMulti
  1034.           THEN
  1035.             IF ((index <= saveIndex) & (index > oldIndex)) OR 
  1036.                ((index >= saveIndex) & (index < oldIndex))
  1037.             THEN
  1038.               (* vorherige togglen *)
  1039.               IF index > oldIndex
  1040.               THEN
  1041.                 FOR i := oldIndex TO index - 1 DO
  1042.                   selectEntry (infoList, i, isSel, TRUE, FALSE, 0);
  1043.                 END;
  1044.               ELSE
  1045.                 FOR i := oldIndex TO index + 1 BY -1 DO
  1046.                   selectEntry (infoList, i, isSel, TRUE, FALSE, 0);
  1047.                 END;
  1048.               END;
  1049.               oldIndex := index;
  1050.             ELSIF ((index < saveIndex) & (index < oldIndex)) OR 
  1051.                   ((index > saveIndex) & (index > oldIndex))
  1052.             THEN
  1053.               IF index > oldIndex
  1054.               THEN
  1055.                 FOR i := index TO oldIndex + 1 BY -1 DO
  1056.                   selectEntry (infoList, i, isSel, TRUE, FALSE, 0);
  1057.                 END;
  1058.               ELSE
  1059.                 FOR i := index TO oldIndex - 1 DO
  1060.                   selectEntry (infoList, i, isSel, TRUE, FALSE, 0);
  1061.                 END;
  1062.               END;
  1063.               oldIndex := index;
  1064.             END;
  1065.           ELSIF selMode = smOne
  1066.           THEN
  1067.             IF index # oldIndex
  1068.             THEN
  1069.               selectEntry (listInfo, index, isSel, TRUE, FALSE, 0);
  1070.               IF isSel THEN 
  1071.                 selIndex := index; 
  1072.               ELSE
  1073.                 index := selIndex;
  1074.               END;
  1075.               oldIndex := index;
  1076.             END;
  1077.           END;
  1078.           (* Und jetzt die Tasten wieder abfragen *)
  1079.           MagicAES.GrafMkstate (mx, my, button, kstate);
  1080.         END;
  1081.         RETURN index
  1082.       ELSIF clicks = 0
  1083.       THEN
  1084.         RETURN index
  1085.       END;
  1086.     ELSE
  1087.       (* Jetzt noch nachsehen, ob es im Hintergrundrechteck liegt und 
  1088.        * dann ggf. warten, bis die Maustaste losgelassen wird.
  1089.        *)
  1090.       IF tree # NIL
  1091.       THEN
  1092.         mtUtils.CalcArea (tree, boxbgindex, br);
  1093.         IF RectFuncs.IsInRect (mx, my, br)
  1094.         THEN
  1095.           (* Warten, bis die Maustaste losgelassen wird 
  1096.            *)
  1097.           REPEAT
  1098.             MagicAES.GrafMkstate (mx, my, button, kstate);
  1099.           UNTIL ~(0 IN button);
  1100.         END;
  1101.       END; 
  1102.     END;
  1103.     RETURN -1
  1104.   END;
  1105. END ListClick;
  1106.  
  1107. PROCEDURE ListUpdateEntry (listInfo : LISTINFO; entry: lINTEGER);
  1108. (* Einen bestimmten Eintrag neu zeichnen lassen, falls n”tig
  1109.  *)
  1110. BEGIN
  1111.   (* Wir lassen den einfach neuzeichnen *)
  1112.   showEntry (listInfo, entry, SHORT (entry - listInfo^.startIndex), listInfo^.area);
  1113. END ListUpdateEntry;
  1114.  
  1115. PROCEDURE ListInvertEntry (listInfo: LISTINFO; entry: lINTEGER);
  1116. (* Der Eintrag entry soll (extern) selektiert werden, den Rest handhaben
  1117.  * Ntzlich fr Autolocator
  1118.  *)
  1119.   VAR isSel : BOOLEAN;
  1120. BEGIN
  1121.   (* Wir lassen den einfach neuzeichnen *)
  1122.   positionList (listInfo);
  1123.   selectEntry (listInfo, entry, isSel, FALSE, FALSE, 0);
  1124.   ListScroll2Selection (listInfo, TRUE);
  1125. END ListInvertEntry;
  1126.  
  1127. PROCEDURE ListDeselEntry (listInfo: LISTINFO; entry: lINTEGER);
  1128. (* Deselektiert den Eintrag entry, falls dieser selektiert ist *)
  1129. BEGIN
  1130.   positionList (listInfo);
  1131.   deselectEntry (listInfo, entry, FALSE);
  1132. END ListDeselEntry;
  1133.  
  1134. PROCEDURE ListScroll2Selection (listInfo: LISTINFO; drawIt: BOOLEAN);
  1135. (* Scrollt die Liste so, daž der erste selektierte Eintrag 
  1136.  * sichtbar ist. 
  1137.  *)
  1138. BEGIN
  1139.   WITH listInfo^ DO
  1140.     lastIndex := ListFirstSelected (listInfo);
  1141.     (* Und jetzt zentrieren. Abfrage ist nicht n”tig, da 
  1142.      * schon in CenterEntry drin
  1143.      *)
  1144.     CenterEntry (listInfo, lastIndex, drawIt);
  1145.   END;
  1146. END ListScroll2Selection;
  1147.  
  1148. PROCEDURE ListPgDown (listInfo : LISTINFO);
  1149.   VAR oldStart : lINTEGER;
  1150. BEGIN
  1151.  WITH listInfo^ DO 
  1152.   positionList (listInfo);
  1153.   oldStart := startIndex;
  1154.   INC (startIndex, lines);
  1155.   IF startIndex+(LONG(lines)-1) > listLength
  1156.   THEN
  1157.     startIndex := listLength-LONG(lines) + 1
  1158.   END;
  1159.   IF startIndex < 1 THEN startIndex := 1 END;
  1160.   IF oldStart # startIndex
  1161.   THEN
  1162.     DialSlider.SetSliderPos (vSlid, startIndex-1, TRUE);
  1163.     showAll (listInfo, area);
  1164.   END;
  1165.  END;
  1166. END ListPgDown;
  1167.  
  1168. PROCEDURE ListPgUp (listInfo : LISTINFO);
  1169.   VAR oldStart : lINTEGER;
  1170. BEGIN
  1171.   WITH listInfo^ DO
  1172.     positionList (listInfo);
  1173.     oldStart := startIndex;
  1174.     IF startIndex > LONG(lines) THEN
  1175.       DEC (startIndex,lines)
  1176.     ELSE
  1177.       startIndex := 1
  1178.     END;
  1179.     IF startIndex # oldStart THEN
  1180.       DialSlider.SetSliderPos (vSlid, startIndex-1,TRUE);
  1181.       showAll (listInfo, area);
  1182.     END;
  1183.   END;
  1184. END ListPgUp;
  1185.  
  1186. PROCEDURE ListLnDown (listInfo : LISTINFO);
  1187. BEGIN
  1188.   WITH listInfo^ DO
  1189.     positionList (listInfo);
  1190.     IF startIndex+LONG(lines-1) < listLength
  1191.     THEN
  1192.       scrollV (listInfo, startIndex+1);
  1193.       DialSlider.SetSliderPos (vSlid, startIndex-1, TRUE);
  1194.     END;
  1195.   END;
  1196. END ListLnDown;
  1197.  
  1198. PROCEDURE ListLnUp   (listInfo : LISTINFO);
  1199. BEGIN
  1200.   WITH listInfo^ DO
  1201.     positionList (listInfo);
  1202.     IF startIndex > 1
  1203.     THEN
  1204.       scrollV (listInfo, startIndex-1);
  1205.       DialSlider.SetSliderPos (vSlid, startIndex-1, TRUE);
  1206.     END;
  1207.   END;
  1208. END ListLnUp;
  1209.  
  1210. PROCEDURE ListFirst (listInfo: LISTINFO);
  1211.   VAR oldStart : LONGINT;
  1212. BEGIN
  1213.   WITH listInfo^ DO
  1214.     positionList (listInfo);
  1215.     oldStart := startIndex;
  1216.     startIndex := 1;
  1217.     IF oldStart # startIndex
  1218.     THEN
  1219.       DialSlider.SetSliderPos (vSlid, startIndex-1, TRUE);
  1220.       showAll (listInfo, area);
  1221.     END;
  1222.   END;
  1223. END ListFirst;
  1224.  
  1225. PROCEDURE ListLast (listInfo: LISTINFO);
  1226.   VAR oldStart : LONGINT;
  1227. BEGIN
  1228.   WITH listInfo^ DO
  1229.     positionList (listInfo);
  1230.     oldStart := startIndex;
  1231.     startIndex := listLength - LONG(lines) + 1;
  1232.     IF oldStart # startIndex
  1233.     THEN
  1234.       DialSlider.SetSliderPos (vSlid, startIndex-1, TRUE);
  1235.       showAll (listInfo, area);
  1236.     END;
  1237.   END;
  1238. END ListLast;
  1239.  
  1240. PROCEDURE ListPgRight (listInfo: LISTINFO);
  1241.   VAR newOffset : INTEGER;
  1242. BEGIN
  1243.   WITH listInfo^ DO
  1244.     positionList (listInfo);
  1245.     IF hpos >= area.w THEN
  1246.       newOffset := hpos - area.w;
  1247.     ELSE
  1248.       newOffset := 0
  1249.     END;
  1250.     scrollH (listInfo, newOffset);
  1251.     DialSlider.SetSliderPos (hSlid, hpos, TRUE);
  1252.   END;
  1253. END ListPgRight;
  1254.  
  1255. PROCEDURE ListPgLeft (listInfo : LISTINFO);
  1256.   VAR newOffset : INTEGER;
  1257. BEGIN
  1258.   WITH listInfo^ DO
  1259.     positionList (listInfo);
  1260.     IF hpos < maxWidth - area.w THEN
  1261.       newOffset := hpos + area.w;
  1262.     ELSE
  1263.       newOffset := maxWidth - area.w
  1264.     END;
  1265.     scrollH (listInfo, newOffset);
  1266.     DialSlider.SetSliderPos (hSlid, hpos, TRUE);
  1267.   END;
  1268. END ListPgLeft;
  1269.  
  1270. PROCEDURE ListLnRight (listInfo: LISTINFO);
  1271. BEGIN
  1272.   WITH listInfo^ DO
  1273.     positionList (listInfo);
  1274.     scrollH (listInfo, hpos - hstep);
  1275.     DialSlider.SetSliderPos (hSlid, hpos, TRUE);
  1276.   END;
  1277. END ListLnRight;
  1278.  
  1279. PROCEDURE ListLnLeft (listInfo : LISTINFO);
  1280. BEGIN
  1281.   WITH listInfo^ DO
  1282.     positionList (listInfo);
  1283.     scrollH (listInfo, hpos + hstep);
  1284.     DialSlider.SetSliderPos (hSlid, hpos, TRUE);
  1285.   END;
  1286. END ListLnLeft;
  1287.  
  1288. PROCEDURE doSelect (listInfo: LISTINFO; newIdx: lINTEGER): lINTEGER;
  1289.   VAR isSel : BOOLEAN;
  1290. BEGIN
  1291.   WITH listInfo^ DO
  1292.     positionList (listInfo);
  1293.     DialSlider.SetSliderPos (vSlid, startIndex-1, TRUE); 
  1294.     CenterEntry (listInfo, newIdx, TRUE);
  1295.     IF (newIdx >= 0) & (newIdx # lastIndex) 
  1296.     THEN
  1297.       selectEntry (listInfo, newIdx, isSel, TRUE, FALSE, 0);
  1298.     END;
  1299.     (*
  1300.     ListScroll2Selection (listInfo, TRUE);
  1301.     *)
  1302.     lastIndex := newIdx;
  1303.     RETURN lastIndex;
  1304.   END;
  1305. END doSelect;
  1306.  
  1307. (* Selektion innerhalb der Liste verchieben *)
  1308. PROCEDURE ListSelUp (listInfo: LISTINFO): lINTEGER;
  1309.   VAR newIdx : lINTEGER;
  1310. BEGIN
  1311.   WITH listInfo^ DO
  1312.     positionList (listInfo);
  1313.     IF (lastIndex < startIndex) OR (lastIndex >= startIndex + LONG(lines))
  1314.     THEN
  1315.       newIdx := -1;
  1316.     ELSIF (lastIndex > 1)
  1317.     THEN
  1318.       newIdx := lastIndex - 1;
  1319.     ELSE
  1320.       newIdx := startIndex + LONG(lines)-1;
  1321.     END;
  1322.     newIdx := findUp (listInfo, newIdx);
  1323.     RETURN doSelect (listInfo, newIdx);
  1324.   END;
  1325. END ListSelUp;
  1326.  
  1327. PROCEDURE ListSelPgUp (listInfo: LISTINFO): lINTEGER;
  1328.   VAR newIdx : lINTEGER;
  1329. BEGIN
  1330.   WITH listInfo^ DO
  1331.     positionList (listInfo);
  1332.     IF (lastIndex < startIndex) OR (lastIndex >= startIndex + LONG(lines))
  1333.     THEN
  1334.       ListPgUp (listInfo);
  1335.       newIdx := -1
  1336.     ELSIF (lastIndex > LONG(lines))
  1337.     THEN
  1338.       newIdx := lastIndex - LONG(lines)(* - 1*);
  1339.     ELSIF (lastIndex > 0)
  1340.     THEN
  1341.       newIdx := 1
  1342.     ELSIF lastIndex < 0
  1343.     THEN
  1344.       ListPgUp (listInfo);
  1345.       newIdx := -1
  1346.     END;
  1347.     newIdx := findUp (listInfo, newIdx);
  1348.     CenterEntry (listInfo, newIdx, TRUE);
  1349.     RETURN doSelect (listInfo, newIdx);
  1350.   END;
  1351. END ListSelPgUp;
  1352.  
  1353. PROCEDURE ListSelDown (listInfo: LISTINFO): lINTEGER;
  1354.   VAR newIdx : lINTEGER;
  1355. BEGIN
  1356.   WITH listInfo^ DO
  1357.     positionList (listInfo);
  1358.     IF lastIndex < listLength
  1359.     THEN
  1360.       IF (lastIndex < startIndex) OR (lastIndex >= startIndex + LONG(lines))
  1361.       THEN
  1362.         newIdx := -1
  1363.       ELSIF (lastIndex > 0) 
  1364.       THEN
  1365.         newIdx := lastIndex + 1;
  1366.       ELSE
  1367.         newIdx := startIndex;
  1368.       END;
  1369.       newIdx := findDown (listInfo, newIdx);
  1370.       RETURN doSelect (listInfo, newIdx);
  1371.     END;
  1372.     RETURN lastIndex;
  1373.   END;
  1374. END ListSelDown;
  1375.  
  1376. PROCEDURE ListSelPgDown (listInfo: LISTINFO): lINTEGER;
  1377.   VAR newIdx : lINTEGER;
  1378. BEGIN
  1379.   WITH listInfo^ DO
  1380.     positionList (listInfo);
  1381.     IF lastIndex < listLength
  1382.     THEN
  1383.       IF (lastIndex < startIndex) OR (lastIndex >= startIndex + LONG(lines))
  1384.       THEN
  1385.         ListPgDown(listInfo);
  1386.         newIdx := startIndex
  1387.       ELSIF (lastIndex > 0) & (lastIndex < listLength - LONG(lines))
  1388.       THEN
  1389.         newIdx := lastIndex + LONG(lines);
  1390.       ELSIF (lastIndex > 0)
  1391.       THEN
  1392.         newIdx := listLength;
  1393.       ELSE
  1394.         ListPgDown(listInfo);
  1395.         newIdx := startIndex;
  1396.       END;
  1397.       newIdx := findDown (listInfo, newIdx);
  1398.       CenterEntry (listInfo, newIdx, TRUE);
  1399.       RETURN doSelect (listInfo, newIdx);
  1400.     END;
  1401.     RETURN lastIndex;
  1402.   END;
  1403. END ListSelPgDown;
  1404.  
  1405. PROCEDURE ListSelFirst (listInfo: LISTINFO): lINTEGER;
  1406. BEGIN
  1407.   positionList (listInfo);
  1408.   scrollV (listInfo, 0);
  1409.   RETURN doSelect (listInfo, findUp (listInfo, 1))
  1410. END ListSelFirst;
  1411.  
  1412. PROCEDURE ListSelLast  (listInfo: LISTINFO): lINTEGER;
  1413. BEGIN
  1414.   positionList (listInfo);
  1415.   scrollV (listInfo, listInfo^.listLength - LONG(listInfo^.lines)+1);
  1416.   RETURN doSelect (listInfo, findDown (listInfo, listInfo^.listLength))
  1417. END ListSelLast;
  1418.  
  1419. PROCEDURE ListListElems (listInfo: LISTINFO): lINTEGER;
  1420.   VAR ll: lINTEGER;
  1421.       ww: sINTEGER;
  1422. BEGIN
  1423.   WITH listInfo^ DO
  1424.     listElems (list, ll, ww);
  1425.     RETURN ll;
  1426.   END;
  1427. END ListListElems;
  1428.  
  1429. PROCEDURE ListFirstSelected (listInfo: LISTINFO) : lINTEGER;
  1430. (* GIbt den ersten selektieren Eintrag zurck, -1 im Fehlerfall
  1431.  *)
  1432.   VAR pt : ADDRESS;
  1433.       i  : lINTEGER;
  1434.       ll : lINTEGER;
  1435.       ww : sINTEGER;
  1436.       
  1437. BEGIN
  1438.   WITH listInfo^ DO
  1439.     lastIndex := -1;
  1440.     listElems (list, ll, ww);
  1441.     listLength := ll;
  1442.     resetList (list);
  1443.     pt := nextEntry (list);
  1444.     i := 1;
  1445.     WHILE (pt # NIL) & (lastIndex < 0) DO 
  1446.       IF isSelected (pt, env)
  1447.       THEN
  1448.         lastIndex := i;
  1449.       END;
  1450.       INC (i);
  1451.       pt := nextEntry (list);
  1452.     END;
  1453.     RETURN lastIndex;
  1454.   END;
  1455. END ListFirstSelected;
  1456.  
  1457. PROCEDURE ListFindEntry (listInfo: LISTINFO; index : lINTEGER) : ADDRESS;
  1458. BEGIN
  1459.   RETURN findListEntry (listInfo, index);
  1460. END ListFindEntry;
  1461.  
  1462. BEGIN
  1463.   infoList := NIL;
  1464.   (* create  MFDB for Screen *)
  1465.   sourceMem.fdAddr := ADDRESS(0L);
  1466.   destMem := sourceMem;
  1467.   (* Init der anderen Variablen *)
  1468.   MagicAES.WindGet (0, MagicAES.WFWORKXYWH, deskSize); (* Gr”že des Desktops abfragen *)
  1469. END ListMan.
  1470.